#ifndef SERVER_MASTERS_MANAGER
#error "This file can't be compiled alone, you must compile main.cpp"
#endif // SERVER_MASTERS_MANAGER
#ifndef SERVICE_CPP
#define SERVICE_CPP
void __stdcall serviceMain(int32_t argc,char **argv){
    int32_t ServiceStatus = E_FAIL;
    // Register service
    GlobalStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME,serviceCtrlHandler);
    if(GlobalStatusHandle == 0) return;
    bzero(&GlobalServiceStatus,sizeof(GlobalServiceStatus));
    GlobalServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    GlobalServiceStatus.dwControlsAccepted = 0;
    GlobalServiceStatus.dwCurrentState = SERVICE_START_PENDING;
    GlobalServiceStatus.dwWin32ExitCode = 0;
    GlobalServiceStatus.dwServiceSpecificExitCode = 0;
    GlobalServiceStatus.dwCheckPoint = 0;
    if(SetServiceStatus(GlobalStatusHandle,&GlobalServiceStatus) == false){
        OutputDebugString("Service installer: serviceMain : setServiceStatus returned error");
    }
    // Start service
    GlobalServiceStopEvent = CreateEvent(NULL,true,false,NULL);
    if(GlobalServiceStopEvent == NULL){
        // Error creating event
        // We can't start, we will exit
        GlobalServiceStatus.dwControlsAccepted = 0;
        GlobalServiceStatus.dwCurrentState = SERVICE_STOPPED;
        GlobalServiceStatus.dwWin32ExitCode = GetLastError();
        GlobalServiceStatus.dwCheckPoint = 1;
        if(SetServiceStatus(GlobalStatusHandle,&GlobalServiceStatus) == false){
            OutputDebugString("Service installer: serviceMain : setServiceStatus returned error");
        }
        return;
    }
    // We are starting the service
    GlobalServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    GlobalServiceStatus.dwCurrentState = SERVICE_RUNNING;
    GlobalServiceStatus.dwWin32ExitCode = 0;
    GlobalServiceStatus.dwCheckPoint = 0;
    if(SetServiceStatus(GlobalStatusHandle,&GlobalServiceStatus) == false){
        OutputDebugString("Service installer: serviceMain : setServiceStatus returned error");
    }
    // Start service main thread
    HANDLE ServiceWorkerThread = CreateThread(NULL,0,serviceWorkerThread,NULL,0,NULL);
    // Wait until the workerThread exits
    WaitForSingleObject(ServiceWorkerThread,INFINITE);
    // Stop service event handling
    CloseHandle(GlobalServiceStopEvent);
    GlobalServiceStatus.dwControlsAccepted = 0;
    GlobalServiceStatus.dwCurrentState = SERVICE_STOPPED;
    GlobalServiceStatus.dwWin32ExitCode = 0;
    GlobalServiceStatus.dwCheckPoint = 3;
    if(SetServiceStatus(GlobalStatusHandle,&GlobalServiceStatus) == false){
        OutputDebugString("Service installer: serviceMain : setServiceStatus returned error");
    }
}
VOID WINAPI serviceCtrlHandler(DWORD Control){
    switch(Control){
        case SERVICE_CONTROL_STOP :
            if(GlobalServiceStatus.dwCurrentState != SERVICE_RUNNING) break; // Service is not running
            // Other tasks to stop the Windows service
            GlobalServiceStatus.dwControlsAccepted = 0;
            GlobalServiceStatus.dwCurrentState = SERVICE_STOP_PENDING;
            GlobalServiceStatus.dwWin32ExitCode = 0;
            GlobalServiceStatus.dwCheckPoint = 4;
            if(SetServiceStatus(GlobalStatusHandle,&GlobalServiceStatus) == false){
                OutputDebugString("Service installer: serviceCtrl : setServiceStatus returned error");
            }
            SetEvent(GlobalServiceStopEvent);
            break;
        default:
            break;
    }
}
DWORD __stdcall serviceWorkerThread(LPVOID lpParam){
    // Check if the service has been requested to stop
    ofstream LogFile;
    LogFile.open("/service.log",std::ios::app);
    LogFile << getFormatedDate() << ": Service is now running\r\n";
    LogFile.flush();
    LogFile.clear();
    LogFile.close();
    while(WaitForSingleObject(GlobalServiceStopEvent,0) != WAIT_OBJECT_0){
        sleep(1);
    }
    LogFile.open("/service.log",std::ios::app);
    LogFile << getFormatedDate() << ": Service stopped\r\n";
    LogFile.flush();
    LogFile.close();
    return ERROR_SUCCESS;
}
#endif // SERVICE_CPP
